﻿using Abp.Application.Services.Dto;
using Abp.Auditing;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using ARchGL.Platform.Authorization.Users.Dto;
using ARchGL.Platform.Utils;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ARchGL.Platform.Authorization.Users
{
    [AbpAuthorize]
    public class UserLoginAppService : PlatformAppServiceBase, IUserLoginAppService
    {
        private readonly IRepository<UserLoginAttempt, long> _userLoginAttemptRepository;
        private readonly AbpLoginResultTypeHelper abpLoginResultTypeHelper;

        public UserLoginAppService(IRepository<UserLoginAttempt, long> userLoginAttemptRepository,
            AbpLoginResultTypeHelper _abpLoginResultTypeHelper)
        {
            _userLoginAttemptRepository = userLoginAttemptRepository;
            abpLoginResultTypeHelper = _abpLoginResultTypeHelper;
        }

        /// <summary>
        /// 获取当前用户最近 10 条登录日志
        /// </summary>
        /// <returns></returns>
        [DisableAuditing]
        public async Task<ListResultDto<UserLoginAttemptDto>> GetRecentUserLoginAttempts()
        {
            var userId = AbpSession.GetUserId();

            var loginAttempts = await _userLoginAttemptRepository.GetAll()
                .Where(la => la.UserId == userId)
                .OrderByDescending(la => la.CreationTime)
                .Take(10)
                .ToListAsync();

            return new ListResultDto<UserLoginAttemptDto>(ObjectMapper.Map<List<UserLoginAttemptDto>>(loginAttempts));
        }

        /// <summary>
        /// 获取用户登录日志（带分页）
        /// </summary>
        /// <param name="input">筛选条件</param>
        /// <returns></returns>
        public async Task<PagedResultDto<UserLoginAttemptDto>> QueryRecentUserLoginAttemptsPagedList(UserLoginAttemptInput input)
        {
            var userId = input.UserId.HasValue ? input.UserId : AbpSession.GetUserId(); //判断查询指定用户还是当前登录用户

            var query = _userLoginAttemptRepository.GetAll()
                .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), x => x.UserNameOrEmailAddress.Contains(input.Filter) || x.ClientIpAddress.Contains(input.Filter) || x.BrowserInfo.Contains(input.Filter))
                .WhereIf(!input.QueryAll, x => x.UserId == userId);

            var data = await query.OrderByDescending(x => x.CreationTime).PageByAsync(input);

            var result = new PagedResultDto<UserLoginAttemptDto>(query.Count(), ObjectMapper.Map<List<UserLoginAttemptDto>>(data.ToList()));
            Filter(result);

            return result;
        }

        private void Filter(PagedResultDto<UserLoginAttemptDto> result)
        {
            foreach (var item in result.Items)
            {
                if (!System.Text.RegularExpressions.Regex.IsMatch(item.ClientIpAddress, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"))
                    item.ClientIpAddress = "127.0.0.1";

                var type = (AbpLoginResultType)Enum.Parse(typeof(AbpLoginResultType), item.Result);
                item.Result = abpLoginResultTypeHelper.CreateLocalizedMessageForFailedLoginAttempt(type, item.TenancyName);
            }
        }
    }
}